package ipebg.mzk.common.core.dao.impl;

import ipebg.mzk.common.core.dao.IMongoDao;

import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

@Repository("mongoDao")
public class MongoDao<T> implements IMongoDao{
	private static final Logger log = Logger.getLogger(MongoDao.class);
	@Autowired
	protected MongoTemplate mongoTemplate;
	
	protected Class<T> clazz;

	public MongoDao() {}

	// constants
	public MongoDao(Class<T> clazz) {
		this.clazz = clazz;
	}
	
	
	
	@Override
	public void save(Object t) {
		this.mongoTemplate.save(t);
	}
	
	/**
     * 根据Id从Collection中查询对象
     * @param id
     * 实体对象的Id,对应Collection中记录的_id字段. 
     * 需要说明的是,Mongdo自身没有主键自增机制.解决方法
     * 实体入库的时候,程序中为实体赋主键值.
     * 实体入库的时候,在mongodb中自定义函数实现主键自增机制.定义方法同js代码类似
     * @return
     */
    public T queryById(String id) {
        Query query = new Query();
        Criteria criteria = Criteria.where("_id").is(id);
        query.addCriteria(criteria);
        log.info("[Mongo Dao ]queryById:" + query);
        return this.mongoTemplate.findOne(query, this.clazz);
    }

    /**
     * 根据条件查询集合
     * @param query        
     * 查询条件
     * @return
     * 满足条件的集合
     */
    public List<T> queryList(Query query){
        log.info("[Mongo Dao ]queryList:" + query);
        return this.mongoTemplate.find(query, this.clazz);
    }
    
    
    /**
     * 通过条件查询单个实体
     * @param query
     * @return
     */
    public T queryOne(Query query){
        log.info("[Mongo Dao ]queryOne:" + query);
        return this.mongoTemplate.findOne(query, this.clazz);
    }


    /** 分页查询操作说明:查询单个用的是mongoTemplate.findOne方法,查询多条的用的是mongoTemplate.find.
     * 通过条件进行分页查询
     * @param query
     *                     查询条件
     * @param start
     *                     查询起始值 
     *                     <strong> 类似mysql查询中的 limit start, size 中的 start</strong>
     * @param size
     *                     查询大小
     *                     <strong> 类似mysql查询中的 limit start, size 中的 size</strong>
     * @return
     *                     满足条件的集合
     */
    public List<T> getPage(Query query, int start, int size){
        query.skip(start);
        query.limit(size);
        log.info("[Mongo Dao ]queryPage:" + query + "(" + start +"," + size +")");
        List<T> lists = this.mongoTemplate.find(query, clazz);
        return lists;
    }
    
    /**
     * 根据条件查询库中符合记录的总数,为分页查询服务
     * @param query
     *                     查询条件
     * @return
     *                     满足条件的记录总数
     */
    public Long getCount(Query query){
        log.info("[Mongo Dao ]queryPageCount:" + query);
        return this.mongoTemplate.count(query, clazz);
    }
    
    
    public void deleteByQuery(Query query){
    	log.info("[Mongo Dao ] deleteByQuery:" + query);
    	com.mongodb.WriteResult result = this.mongoTemplate.remove(query, clazz);
    	System.out.print(result);
    }
    
    /**
     * 根据Id删除用户
     * @param id
     */
    public void deleteById(String id) {
        Criteria criteria = Criteria.where("_id").in(id);
        if(null!=criteria){
            Query query = new Query(criteria);
            log.info("[Mongo Dao ]deleteById:" + query);
            if(null!=query && this.queryOne(query)!=null){
            	T t = this.queryOne(query);
            	this.delete(t);
                //this.delete(query); //alt by LXQ
            }
        }
    }
    
    /**
     * 删除对象
     * @param t
     */
    public void delete(T t){
        log.info("[Mongo Dao ]delete:" + t);
        this.mongoTemplate.remove(t);
    }
    
/*修改操作:
说明:Mongodb的修改操作大致有3中.
mongoTemplate.updateFirst操作、mongoTemplate.updateMulti操作、this.mongoTemplate.upsert操作.
分别表示修改第一条、修改符合条件的所有、修改时如果不存在则添加.
修改满足条件的第一条记录*/
    /**
     * 更新满足条件的第一个记录
     * @param query
     * @param update
     */
    public void updateFirst(Query query,Update update){
        log.info("[Mongo Dao ]updateFirst:query(" + query + "),update(" + update + ")");
        this.mongoTemplate.updateFirst(query, update, this.clazz);
    }
    
    /**
     * 更新满足条件的所有记录
     * @param query
     * @param update
     */
    public void updateMulti(Query query, Update update){
        log.info("[Mongo Dao ]updateMulti:query(" + query + "),update(" + update + ")");
        this.mongoTemplate.updateMulti(query, update, this.clazz);
    }
    
    /**
     * 查找更新,如果没有找到符合的记录,则将更新的记录插入库中
     * @param query
     * @param update
     */
    public void updateInser(Query query, Update update){
        log.info("[Mongo Dao ]updateInser:query(" + query + "),update(" + update + ")");
        this.mongoTemplate.upsert(query, update, this.clazz);
    }

	
}
